using System;
using System.Drawing;
using Wilco.SyntaxHighlighting.Engine.Highlighter;
using Wilco.SyntaxHighlighting.Engine.Node.Implementation.Word;
using Wilco.SyntaxHighlighting.Engine.Parser;
using Wilco.SyntaxHighlighting.Engine.Scanner;
using Wilco.SyntaxHighlighting.Engine.Scanner.Implementation;

namespace Wilco.SyntaxHighlighting.Engine.Highlighter.Implementation
{
    /// <summary>
    /// Represents a Python syntax highlighter.
    /// </summary>
    public class PythonHighlighter : HighlighterBase
    {
        /// <summary>
        /// Initializes a new instance of a <see cref="PythonHighlighter"/> class.
        /// </summary>
        public PythonHighlighter() : this(null)
        {
        }

        /// <summary>
        /// Initializes a new instance of a <see cref="PythonHighlighter"/> class.
        /// </summary>
        /// <param name="parser">The parser which will be used to parse the source code.</param>
        public PythonHighlighter(IParser parser) : base(parser)
        {
            Name = "Python";
            FullName = "Python";
            TagValues.AddRange(new String[] { "py" });
            FileExtensions.Add("py");
        }

        /// <summary>
        /// Creates a new instance (clone) of this highlighter.
        /// </summary>
        /// <returns></returns>
        public override HighlighterBase Create()
        {
            return new PythonHighlighter(Parser);
        }

        /// <summary>
        /// Builds a word scanner.
        /// </summary>
        /// <returns>A <see cref="WordScanner"/> object.</returns>
        protected override IScanner BuildWordScanner()
        {
            WordScanner scanner = new WordScanner(Tokenizer, ScannerResult);
            scanner.WordNodes = new WordNode[1];
            scanner.WordNodes[0] = new WordNode();
            scanner.WordNodes[0].ForeColor = Color.Blue;
            scanner.WordNodes[0].Entities.AddRange(GetKeywords());
            return scanner;
        }

        /// <summary>
        /// Gets an array of registered keywords.
        /// </summary>
        /// <returns>An array of keywords.</returns>
        private static string[] GetKeywords()
        {
            string[] keywordList = new string[]
                {
                    "def",
                    "os",
                    "cgi",
                    "time",
                    "Cookie",
                    "htmlxmlsql2000db",
                    "print",
                    "return",
                    "import",
                    "sys",
                    "gc",
                    "weakref",
                    "fpectl",
                    "atexit",
                    "types",
                    "UserDict",
                    "UserList",
                    "UserString",
                    "operator",
                    "inspect",
                    "traceback",
                    "linecache",
                    "pickle",
                    "cPickle",
                    "copy_reg",
                    "shelve",
                    "copy",
                    "marshal",
                    "warnings",
                    "imp",
                    "code",
                    "codeop",
                    "pprint",
                    "repr",
                    "new",
                    "site",
                    "user",
                    "__builtin__",
                    "__main__",
                    "byteorder",
                    "builtin_module_names",
                    "copyright",
                    "dllhandle",
                    "displayhook",
                    "excepthook",
                    "__displayhook__",
                    "__excepthook__",
                    "exc_info",
                    "exc_type",
                    "exc_value",
                    "exc_traceback",
                    "exec_prefix",
                    "executable",
                    "exit",
                    "exitfunc",
                    "getdefaultencoding",
                    "getdlopenflags",
                    "getrefcount",
                    "getrecursionlimit",
                    "_getframe",
                    "hexversion",
                    "last_type",
                    "last_value",
                    "last_traceback",
                    "maxint",
                    "maxunicode",
                    "modules",
                    "path",
                    "platform",
                    "prefix",
                    "ps1",
                    "ps2",
                    "setcheckinterval",
                    "setdefaultencoding",
                    "setdlopenflags",
                    "setprofile",
                    "setrecursionlimit",
                    "settrace",
                    "stdin",
                    "stdout",
                    "stderr",
                    "__stdin__",
                    "__stdout__",
                    "__stderr__",
                    "tracebacklimit",
                    "version",
                    "version_info",
                    "warnoptions",
                    "winver",
                    "enable",
                    "disable",
                    "isenabled",
                    "collect",
                    "set_debug",
                    "get_debug",
                    "get_objects",
                    "set_threshold",
                    "get_threshold",
                    "get_referrers",
                    "garbage",
                    "DEBUG_STATS",
                    "DEBUG_COLLECTABLE",
                    "DEBUG_UNCOLLECTABLE",
                    "DEBUG_INSTANCES",
                    "DEBUG_OBJECTS",
                    "DEBUG_SAVEALL",
                    "DEBUG_LEAK",
                    "ref",
                    "proxy",
                    "getweakrefcount",
                    "getweakrefs",
                    "class",
                    "WeakKeyDictionary",
                    "WeakValueDictionary",
                    "ReferenceType",
                    "ProxyType",
                    "CallableProxyType",
                    "ProxyTypes",
                    "exception",
                    "ReferenceError",
                    "turnon_sigfpe",
                    "turnoff_sigfpe",
                    "FloatingPointError",
                    "register",
                    "NoneType",
                    "TypeType",
                    "IntType",
                    "LongType",
                    "FloatType",
                    "ComplexType",
                    "StringType",
                    "UnicodeType",
                    "TupleType",
                    "ListType",
                    "DictType",
                    "DictionaryType",
                    "FunctionType",
                    "LambdaType",
                    "GeneratorType",
                    "CodeType",
                    "ClassType",
                    "InstanceType",
                    "MethodType",
                    "UnboundMethodType",
                    "BuiltinFunctionType",
                    "BuiltinMethodType",
                    "ModuleType",
                    "FileType",
                    "XRangeType",
                    "SliceType",
                    "EllipsisType",
                    "TracebackType",
                    "FrameType",
                    "BufferType",
                    "StringTypes",
                    "UserDict",
                    "data",
                    "if",
                    "else",
                    "UserList",
                    "MutableString",
                    "__lt__",
                    "__le__",
                    "__eq__",
                    "__ne__",
                    "__ge__",
                    "__gt__",
                    "not_",
                    "truth",
                    "abs",
                    "__abs__",
                    "add",
                    "__add__",
                    "and_",
                    "__and__",
                    "div",
                    "__div__",
                    "floordiv",
                    "__floordiv__",
                    "inv",
                    "invert",
                    "__inv__",
                    "__invert__",
                    "lshift",
                    "__lshift__",
                    "mod",
                    "__mod__",
                    "mul",
                    "__mul__",
                    "neg",
                    "__neg__",
                    "or_",
                    "__or__",
                    "pos",
                    "__pos__",
                    "rshift",
                    "__rshift__",
                    "sub",
                    "__sub__",
                    "truediv",
                    "__truediv__",
                    "xor",
                    "__xor__",
                    "concat",
                    "__concat__",
                    "contains",
                    "__contains__",
                    "countOf",
                    "delitem",
                    "__delitem__",
                    "delslice",
                    "__delslice__",
                    "getitem",
                    "__getitem__",
                    "getslice",
                    "__getslice__",
                    "indexOf",
                    "repeat",
                    "__repeat__",
                    "sequenceIncludes",
                    "setitem",
                    "__setitem__",
                    "setslice",
                    "__setslice__",
                    "isCallable",
                    "isMappingType",
                    "isNumberType",
                    "isSequenceType",
                    "getdoc",
                    "getcomments",
                    "getfile",
                    "getmodule",
                    "getsourcefile",
                    "getsourcelines",
                    "getsource",
                    "getclasstree",
                    "getargspec",
                    "getargvalues",
                    "formatargspec",
                    "formatargvalues",
                    "getmro",
                    "getframeinfo",
                    "getouterframes",
                    "getinnerframes",
                    "currentframe",
                    "stack",
                    "trace",
                    "print_tb",
                    "print_exception",
                    "print_exc",
                    "print_last",
                    "print_stack",
                    "extract_tb",
                    "extract_stack",
                    "format_list",
                    "format_exception_only",
                    "format_exception",
                    "format_tb",
                    "format_stack",
                    "tb_lineno",
                    "getline",
                    "clecheckcache",
                    "dump",
                    "load",
                    "dumps",
                    "loads",
                    "PickleError",
                    "PicklingError",
                    "UnpicklingError",
                    "Pickler",
                    "dump",
                    "clear_memo",
                    "Unpickler",
                    "load",
                    "noload",
                    "constructor",
                    "pickle",
                    "dump",
                    "load",
                    "dumps",
                    "loads",
                    "warn",
                    "warn_explicit",
                    "showwarning",
                    "formatwarning",
                    "filterwarnings",
                    "resetwarnings",
                    "get_magic",
                    "get_suffixes",
                    "find_module",
                    "load_module",
                    "new_module",
                    "lock_held",
                    "PY_SOURCE",
                    "PY_COMPILED",
                    "C_EXTENSION",
                    "PY_RESOURCE",
                    "PKG_DIRECTORY",
                    "C_BUILTIN",
                    "PY_FROZEN",
                    "SEARCH_ERROR",
                    "init_builtin",
                    "init_frozen",
                    "is_builtin",
                    "is_frozen",
                    "load_compiled",
                    "load_dynamic",
                    "load_source",
                    "InteractiveInterpreter",
                    "InteractiveConsole",
                    "interact",
                    "compile_command",
                    "runsource",
                    "runcode",
                    "showsyntaxerror",
                    "showtraceback",
                    "write",
                    "interact",
                    "push",
                    "resetbuffer",
                    "raw_input",
                    "compile_command",
                    "Compile",
                    "CommandCompiler",
                    "PrettyPrinter",
                    "pformat",
                    "pprint",
                    "isreadable",
                    "isrecursive",
                    "saferepr",
                    "Repr",
                    "aRepr",
                    "repr",
                    "maxlevel",
                    "maxdict",
                    "maxlist",
                    "maxtuple",
                    "maxlong",
                    "maxstring",
                    "maxother",
                    "repr",
                    "repr1",
                    "repr_type",
                    "instance",
                    "instancemethod",
                    "function",
                    "code",
                    "module",
                    "classobj",
                    "ascii_letters",
                    "ascii_lowercase",
                    "ascii_uppercase",
                    "digits",
                    "hexdigits",
                    "letters",
                    "lowercase",
                    "octdigits",
                    "punctuation",
                    "printable",
                    "uppercase",
                    "whitespace",
                    "atof",
                    "atoi",
                    "atol",
                    "capitalize",
                    "capwords",
                    "expandtabs",
                    "find",
                    "rfind",
                    "index",
                    "rindex",
                    "count",
                    "lower",
                    "maketrans",
                    "split",
                    "splitfields",
                    "join",
                    "joinfields",
                    "lstrip",
                    "rstrip",
                    "strip",
                    "swapcase",
                    "translate",
                    "upper",
                    "ljust",
                    "rjust",
                    "center",
                    "zfill",
                    "replace",
                    "search",
                    "match",
                    "split",
                    "findall",
                    "finditer",
                    "sub",
                    "subn",
                    "flags",
                    "groupindex",
                    "pattern",
                    "expand",
                    "group",
                    "groups",
                    "groupdict",
                    "start",
                    "end",
                    "span",
                    "pos",
                    "endpos",
                    "lastgroup",
                    "lastindex",
                    "re",
                    "string",
                    "pack",
                    "unpack",
                    "calcsize",
                    "SequenceMatcher",
                    "Differ",
                    "get_close_matches",
                    "ndiff",
                    "restore",
                    "IS_LINE_JUNK",
                    "IS_CHARACTER_JUNK",
                    "set_seqs",
                    "set_seq1",
                    "set_seq2",
                    "find_longest_match",
                    "get_matching_blocks",
                    "get_opcodes",
                    "ratio",
                    "quick_ratio",
                    "real_quick_ratio",
                    "compare",
                    "fix",
                    "sci",
                    "NotANumber",
                    "StringIO",
                    "getvalue",
                    "close",
                    "InputType",
                    "OutputType",
                    "register",
                    "stream_reader",
                    "stream_writer",
                    "factory",
                    "lookup",
                    "getencoder",
                    "getdecoder",
                    "getreader",
                    "getwriter",
                    "open",
                    "EncodedFile",
                    "encode",
                    "decode",
                    "StreamWriter",
                    "write",
                    "writelines",
                    "reset",
                    "StreamReader",
                    "read",
                    "readline",
                    "readlines",
                    "reset",
                    "StreamRecoder",
                    "StreamReaderWriter",
                    "lookup",
                    "name",
                    "decimal",
                    "digit",
                    "numeric",
                    "category",
                    "bidirectional",
                    "combining",
                    "mirrored",
                    "decomposition"
                };

            Array.Sort(keywordList);
            Array.Reverse(keywordList);

            return keywordList;
        }
    }
}